#include "ExtendLoopController.h"

#include <charconv>

#include "ElecConfigInfo.h"
#include "ConfigManager.h"


bool ExtendLoopController::initialize() noexcept {
    mbeginIndex = MDConst::DEFAULT_INTERNAL_LOOP_COUNT;
    bool result = true;
    try{
    initSlaveController();

    ElecConfigInfo& elecInfo = ConfigManagerSingleton::instance().getExtendDeviceConfig().elecInfo;
    mcurrentVoltageInfos = new CurrentVoltageInfo[mportCount];

    std::string phases;
    if (elecInfo.phaseString.size() > mbeginIndex){
        phases.assign(elecInfo.phaseString, mbeginIndex);
    }
    setPhase(phases);
    mloopPhases.resize(mportCount, 'A');

    if (elecInfo.trippingAlert.size() > mbeginIndex){
        mtrippingAlert.assign(elecInfo.trippingAlert, mbeginIndex);
    }
    mtrippingAlert.resize(mportCount, '1');


    buildCommandAndSavePhase();

    updateLoopControllerConfig(ConfigManagerSingleton::instance().getExtendDeviceConfig().loopControllerInfo);

    allocStatusMemory();

    } catch(std::exception& ex){
        LOG_ERROR(ex.what());
        result = false;
    }

    return result;
}



void ExtendLoopController::buildCommandAndSavePhase() {

    for (SlaveLoopController& slave : mslaveLoopControllers) {
        slave.buildCommandAndSavePhase(std::string_view(&mloopPhases[slave.mgroupInfo.firstIndexInSlave], slave.mgroupInfo.portCount));
    }
}



void ExtendLoopController::initSlaveController() {

    std::string result;
    mchannel.sendStringReturnString("<SLAVE_SUM>", result);

    std::string::size_type pos = result.find_last_of('_');
    std::string loopCountInfo = result.substr(pos + 1, result.size() - pos - 2);
//        std::string::size_type splitterPos = result.find('/', pos);
//        std::from_chars(result[pos], result[splitterPos], count);
    LoopSize_t allLoop = 0, perSlaveLoopCount = 0;
    int  currentLoopNumCount = MDConst::DEFAULT_INTERNAL_LOOP_COUNT;

    for (int i = 0; i < loopCountInfo.size(); ++i) {
        std::from_chars(&loopCountInfo[i], &loopCountInfo[i + 1], perSlaveLoopCount, 16);

        LoopGroupInfo loopGroupTemp(mdeviceType.name, currentLoopNumCount, mchannel.mchannel, perSlaveLoopCount, allLoop);

        mslaveLoopControllers.emplace_back(mdeviceType, i, loopGroupTemp, *this);

        allLoop += perSlaveLoopCount;
        currentLoopNumCount += perSlaveLoopCount;
    }

    LoopSize_t* psize = const_cast<LoopSize_t*>(&mportCount);
    *psize =allLoop;
}






int ExtendLoopController::initLoopGroupInfo(LoopGroupInfos& loopGroups) {

    for (SlaveLoopController& slave : mslaveLoopControllers) {
        loopGroups.emplace_back(slave.mgroupInfo);
    }

    return mslaveLoopControllers.size();
}




bool ExtendLoopController::updateInformation() {

    std::string result;
    for (SlaveLoopController& slave : mslaveLoopControllers) {
        slave.updateInfomation(result);

        parseVoltageCurrent(result, mcurrentVoltageInfos + slave.mgroupInfo.firstIndexInSlave);
    }

    return true;
}



SlaveLoopController* ExtendLoopController::locateSlaveController(int loopIndex, std::size_t& indexInSlave) {
    int indexCount = 0;
    SlaveLoopController* pslave = nullptr;
    for (SlaveLoopController& slave : mslaveLoopControllers) {
        if (indexCount + slave.mgroupInfo.portCount > loopIndex) {
            pslave = &slave;
            indexInSlave = loopIndex - indexCount;
            break;
        }
        indexCount += slave.mgroupInfo.portCount;
    }
    return pslave;
}



void ExtendLoopController::changeAllChannelStatusFunc(const LoopStatus* command, const LoopSize_t& length) {

    int beginIndex = 0;
    int endIndex = 0;
    for (SlaveLoopController& slave : mslaveLoopControllers) {
        endIndex = beginIndex + slave.mgroupInfo.portCount;
        slave.changeAllChannelStatusFunc(command + beginIndex, slave.mgroupInfo.portCount);
        beginIndex = endIndex;
    }
}


void ExtendLoopController::changeSingleChannelStatusFunc(const int& loopIndex, const LoopStatus& status) {
    int indexCount = 0;
    for (SlaveLoopController& slave : mslaveLoopControllers) {
        if (indexCount + slave.mgroupInfo.portCount > loopIndex) {
            return slave.changeSingleChannelStatusFunc(loopIndex - indexCount, status);
        }
        indexCount += slave.mgroupInfo.portCount;
    }
}



